package cn.zdsoft.configuration.service;

import cn.zdsoft.configuration.entity.CustomSerializer;
import cn.zdsoft.configuration.entity.Node;
import cn.zdsoft.configuration.util.StringUtils;
import org.I0Itec.zkclient.ZkClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Created by wangdongdong on 2018/5/14.
 */
public class ZookeeperClient {

    /**
     * 根节点
     */
    public String ROOT_NODE = "/configuration/config";

    /**
     * 超时时间
     */
    public static final int timeout = 5000;

    /**
     * 服务器
     */
    public static final String SERVER = "zk.config.servers";
    public static final String ROOT = "zk.config.root";

    private static final Logger logger = LoggerFactory.getLogger(ZookeeperClient.class);

    private String servers;

    private ZkClient zk = null;

    public void init() {
        Properties properties = mergeProperties();
        if (zk != null) {
            zk.close();
        }

        this.servers = properties.getProperty(SERVER);
        String rootPath = properties.getProperty(ROOT);
        if (StringUtils.isNotBlank(rootPath)) {
            ROOT_NODE = rootPath;
        }

        if (servers == null || "".equals(servers.trim())) {
            throw new IllegalArgumentException("Wrong configurations, please check " + SERVER );
        }
        zk = new ZkClient(servers, timeout);
        zk.setZkSerializer(new CustomSerializer());
    }

    /**
     * 合并配置信息
     *
     * @return
     */
    protected Properties mergeProperties() {

        Properties props = new Properties();
        InputStream is = this.getClass().getResourceAsStream("/config.properties");

        if (is == null) {
            throw new IllegalArgumentException("'config.properties' file not found !");
        }
        try {
            props.load(is);
            is.close();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return props;
    }

    public List<String> getAllProjectNodes() {
        if (zk.exists(ROOT_NODE)) {
            return zk.getChildren(ROOT_NODE);
        }
        return new ArrayList<>();
    }

    public List<String> getEvnsByProject(String proj) {
        return zk.getChildren(ROOT_NODE + "/" + proj);
    }

    public List<Node> getNodeByProjectAndEven(String proj, String evn, String searchStr) {
        List<Node> nodeList = new ArrayList<>();
        String nodePath = ROOT_NODE + "/" + proj + "/" + evn;
        List<String> nodes = zk.getChildren(nodePath);
        nodes.forEach(e->{
            if (e.contains(searchStr.trim())) {
                Node node = new Node();
                node.setName(e);
                String propPath = nodePath + "/" + e;
                if (zk.exists(propPath)) {
                    node.setValue(zk.readData(propPath));
                } else
                    node.setValue("");
                nodeList.add(node);
            }
        });
        return nodeList;
    }

    public void saveNode(String proj, String evn, Node node) {
        if (StringUtils.isBlank(node.getName())) {
            throw new IllegalStateException("配置项不能为空");
        }

        if (StringUtils.isBlank(node.getValue())) {
            throw new IllegalStateException("值不能为空");
        }

        String nodePath = ROOT_NODE + "/" + proj + "/" + evn;
        if (!zk.exists(nodePath)) {
            throw new IllegalStateException("不存在" + nodePath);
        }
        String propPath = nodePath + "/" + node.getName();
        if (zk.exists(propPath)) {
            // 修改
            zk.writeData(propPath, node.getValue());
            return;
        }
        zk.createPersistent(propPath, node.getValue());
    }

    public static void main(String[] args) {
       /* ZookeeperClient client = new ZookeeperClient();
        client.init();
        client.getAllProjectNodes().forEach(e->{
            System.out.println(e);
            client.getEvnsByProject(e).forEach(
                    e1->{
                        System.out.println(e1);
                        client.getNodeByProjectAndEven(e, e1).forEach(System.out::println);
                    }
            );
           }
        );*/
    }

    public void deleteNode(String proj, String evn, String nodeName) {
        if (StringUtils.isBlank(nodeName)) {
            throw new IllegalStateException("配置项不能为空");
        }
        String nodePath = ROOT_NODE + "/" + proj + "/" + evn;
        String propPath = nodePath + "/" + nodeName;
        if (zk.exists(propPath)) {
            // 修改
            zk.delete(propPath);
            return;
        }
        throw new IllegalStateException("该配置项不存在");
    }

    public void importProp(String proj, String evn, List<String> importFile) {
        for (String str : importFile) {
            String[] strList = str.trim().split("=");
            String name = strList[0];
            String value = strList.length < 2 ? "" : strList[1];
            Node node = new Node();
            node.setName(name);
            node.setValue(value);
            saveNode(proj, evn, node);
        }
    }
}
